<?php

namespace app\health\model;

use Exception;
use think\Db;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\DbException;
use think\Hook;
use think\Model;

class HealthOrder extends Model
{
    protected $name = 'health_order';

    protected $autoWriteTimestamp = false;

    protected $append = [
        'status_text'
    ];

    public const STATUS_MAP = [
        1 => '待付款',
        2 => '待发货',
        3 => '待收货',
        4 => '已完成',
        5 => '已取消'
    ];

    public function getStatusTextAttr($val, $data)
    {
        return self::STATUS_MAP[$data['status']] ?? '';
    }

    public function getCreateTimeAttr($val)
    {
        return date('Y-m-d H:i:s', $val);
    }

    /**
     * 关联订单商品
     * @Author 张旭鹏
     * @DateTime 2023-06-15
     */
    public function orderGoods()
    {
        return $this->hasMany(HealthOrderGoods::class, 'order_id');
    }

    /**
     * 获取商品列表
     * @Author 张旭鹏
     * @DateTime 2023-06-20
     */
    public static function getGoodsLists($params = [])
    {
        $confirmType = (int)$params['confirm_type'];
        $goodLists   = [];
        $payPrice    = '0';
        $totalPrice  = '0';
        $goodsIdArr  = []; //商品id
        $cardId      = [];
        if ($confirmType === 1) {
            //购物车结算模式
            $cartGoods = HealthCart::with(['goodsAttr' => ['goods']])->where('id', 'in', $params['cart_id'])->select();
            foreach ($cartGoods as $key => $item) {
                //获取商品规格属性值
                $goodsAttrInfo = $item->goods_attr;
                if ($goodsAttrInfo->stock < $item->number) {
                    // throw new Exception('库存不足');
                }
                //计算商品付款价格
                $currentPayPrice = bcmul($item['number'], $goodsAttrInfo->price, 2);
                //总支付价格
                $payPrice     = bcadd($currentPayPrice, $payPrice, 2);
                $goodLists[]  = [
                    'id'             => $goodsAttrInfo->goods->id,
                    'goods_name'     => $goodsAttrInfo->goods->goods_name,
                    'image'          => empty($goodsAttrInfo->image_url) ? $goodsAttrInfo->goods->image_url : $goodsAttrInfo->image_url,
                    'attr_id'        => $goodsAttrInfo->id,
                    'attr_name'      => $goodsAttrInfo->attr_name,
                    'attr_price'     => $goodsAttrInfo->price,
                    'pay_price'      => $currentPayPrice,
                    'number'         => $item->number,
                    'discount_price' => 0
                ];
                $goodsIdArr[] = $goodsAttrInfo->goods_id;
                $cardId[]     = $item['id'];
            }
            $totalPrice = $payPrice;
        }
        if ($confirmType === 2) {
            //立即购买结算模式
            $buyNumber     = $params['number'] ?? 1;
            $goodsAttrId   = $params['goods_attr_id'];
            $goodsAttrInfo = HealthGoodsAttr::with(['goods'])->where('id', $goodsAttrId)->find();
            if ($goodsAttrInfo->stock < $buyNumber) {
                // throw new Exception('库存不足');
            }
            $payPrice     = bcmul($buyNumber, $goodsAttrInfo['price'], 2);
            $goodLists    = [
                [
                    'id'             => $goodsAttrInfo->goods->id,
                    'goods_name'     => $goodsAttrInfo->goods->goods_name,
                    'image'          => empty($goodsAttrInfo->image_url) ? $goodsAttrInfo->goods->image_url : $goodsAttrInfo->image_url,
                    'attr_id'        => $goodsAttrInfo->id,
                    'attr_name'      => $goodsAttrInfo->attr_name,
                    'attr_price'     => $goodsAttrInfo->price,
                    'pay_price'      => $payPrice,
                    'number'         => $buyNumber,
                    'discount_price' => 0
                ]
            ];
            $totalPrice   = $payPrice;
            $goodsIdArr[] = $goodsAttrInfo->goods_id;
        }
        return [
            'total_price'  => $totalPrice,
            'pay_price'    => $payPrice,
            'goods_lists'  => $goodLists,
            'goods_id_arr' => $goodsIdArr,
            'cart_id'      => $cardId
        ];
    }

    /**
     * 确认订单信息
     * @param array $params
     * @return array
     * @Author 张旭鹏
     * @DateTime 2023-06-15
     */
    public static function confirmInfo($params = [])
    {
        $goodsLists               = self::getGoodsLists($params);
        $data                     = [];
        $data['coupon_list_id']   = $params['coupon_list_id'] ?? 0;                       //优惠券ID
        $data['total_price']      = $goodsLists['total_price'];                           //订单总金额
        $data['pay_price']        = $goodsLists['pay_price'];                             //订单支付金额
        $data['goods_lists']      = $goodsLists['goods_lists'];                           //订单商品列表
        $data['cart_id']          = $goodsLists['cart_id'];                               //购物车ID
        $data['discount_balance'] = 0;                                                    //余额抵扣金额
        $data['discount_price']   = 0;                                                    //优惠券抵扣金额
        $user                     = HealthUser::where('id', $params['user_id'])->find();
        // 优惠券抵扣
        if ($data['coupon_list_id'] > 0) {
            $couponList = HealthCouponList::with(['coupon'])
                ->where('id', $data['coupon_list_id'])
                ->where('user_id', $params['user_id'])
                ->find();
            if (!$couponList) {
                throw new Exception('优惠券不存在');
            }
            if ($couponList->invalid_time < time()) {
                throw new Exception('优惠券已过期');
            }
            if ($couponList->coupon->use_goods_type != 1) {
                //非全场使用,查询配置的商品ID
                $couponUseGoodsIds = explode(',', $couponList->coupon->use_goods_ids);
                $isUseCoupon       = false;
                foreach ($data['goods_lists'] as &$goods) {
                    if (in_array($goods['id'], $couponUseGoodsIds)) {
                        if ($couponList->coupon->condition_type == 2 && $goods['pay_price'] < $couponList->coupon->condition_money) {
                            throw new Exception('商品金额满' . $couponList->coupon->condition_money . '元可使用');
                        }
                        $goods['discount_price'] = $couponList->coupon->money >= $goods['pay_price'] ? $goods['pay_price'] : $couponList->coupon->money;
                        $goods['pay_price']      = bcsub($goods['pay_price'], $goods['discount_price'], 2);
                        $data['discount_price']  = $goods['discount_price'];
                        $isUseCoupon             = true;
                        break;
                    }
                }
                if (!$isUseCoupon) {
                    throw new Exception('没有可以使用的商品');
                }
            } else {
                if ($couponList->coupon->condition_type == 2 && $data['total_price'] < $couponList->coupon->condition_money) {
                    throw new Exception('订单金额满' . $couponList->coupon->condition_money . '元可使用');
                }
                $data['discount_price'] = $couponList->coupon->money >= $data['pay_price'] ? $couponList->coupon->money : bcsub($data['pay_price'], $couponList->coupon->money, 2);
            }
        }
        if ($data['discount_price'] > 0) {
            $data['pay_price'] = bcsub($data['pay_price'], $data['discount_price'], 2);
        }
        //余额抵扣
        $isBalance = $params['is_balance'] ?? 0;
        if ($isBalance) {
            if ($user['balance'] <= 0) {
                throw new Exception('没有可以抵用的余额');
            }
            if ($user['balance'] > $data['pay_price']) {
                $data['discount_balance'] = $data['pay_price'];
                $data['pay_price']        = 0;
            } else {
                $data['discount_balance'] = $user['balance'];
                $data['pay_price']        = bcsub($data['pay_price'], $user['balance'], 2);
            }
        }
        $data['user_balance'] = $user['balance'];
        return $data;
    }

    /**
     * 获取可使用的优惠券列表
     * @Author 张旭鹏
     * @DateTime 2023-06-20
     */
    public static function coupons($params)
    {
        // 获取购买的商品列表及支付金额
        $goodsLists    = self::getGoodsLists($params);
        $coupons       = HealthCouponList::with(['coupon'])
            ->where('user_id', $params['user_id'])
            ->where('status', 0)
            ->where('invalid_time', '>', time())
            ->select();
        $canUseCoupons = [];
        foreach ($coupons as $coupon) {
            if ($coupon->coupon['condition_type'] != 1 && $goodsLists['pay_price'] < $coupon->coupon['condition_money']) {
                continue;
            }

            $condition = $coupon->coupon['condition_type'] == 1
                ? '无金额门槛'
                : '满' . intval($coupon->coupon['condition_money']) . '使用';
            switch ($coupon->coupon['use_goods_type']) {
                case 1:
                    $use_scene = '全场通用';
                    break;
                case 2:
                    $use_scene = '指定商品可用';
                    break;
            }
            $use_goods_ids = explode(',', $coupon->coupon['use_goods_ids']);
            $intersect     = array_intersect($goodsLists['goods_id_arr'], $use_goods_ids);
            if ($coupon->coupon['use_goods_type'] == 2 && count($intersect) === 0) {
                continue;
            }
            $effective_time = '';
            switch ($coupon->coupon['use_time_type']) {
                case 1:
                    $effective_time =
                        date('Y.m.d H:i', $coupon->coupon['use_time_start']) . ' ~ ' .
                        date('Y.m.d H:i', $coupon->coupon['use_time_end']);
                    break;
                case 2:
                    $effective_time = '有效期至' . date('Y年m月d日', $coupon['invalid_time']);
                    break;
                case 3:
                    $effective_time = '领取次日' . $coupon->coupon['use_time'] . '天内可用';
                    break;
            }
            $canUseCoupons[] = [
                'coupon_list_id' => $coupon->id,
                'condition'      => $condition,
                'use_scene'      => $use_scene,
                'coupon_name'    => $coupon->coupon->name,
                'coupon_money'   => $coupon->coupon->money,
                'effective_time' => $effective_time
            ];
        }
        return $canUseCoupons;
    }

    /**
     * 支付成功回调
     * @param HealthOrder $healthOrder
     * @return bool|HealthOrder
     * @throws \think\Exception
     * @Author 张旭鹏
     * @DateTime 2023-06-15
     */
    public static function paySuccess(HealthOrder $healthOrder)
    {
        if ($healthOrder->status == 1) {
            $healthOrder->status     = 2;
            $healthOrder->pay_time   = time();
            $healthOrder->pay_status = 2;
            $healthOrder->save();
            if ($healthOrder->discount_balance > 0) {
                //余额抵扣记录
                HealthUserAccount::expend($healthOrder->user_id, HealthUserAccount::FORM_TYPE_DEDUCTION, HealthUserAccount::ACCOUNT_TYPE_BALANCE, $healthOrder->discount_balance);
            }
            $orderGoods = $healthOrder->orderGoods;
            $goodsId    = [];
            foreach ($orderGoods as $item) {
                $goodsId[] = $item['goods_id'];
            }
            count($goodsId) > 0 && HealthGoods::whereIn('id', $goodsId)->setInc('sales_total');
            // 订单支付成功事件
            $listenParams = ['order_id' => $healthOrder->id, 'user_id' => $healthOrder['user_id']];
            Hook::listen('order_payed_after', $listenParams);
            return $healthOrder;
        }
        return false;
    }

    /**
     * 取消订单
     * @param $orderId
     * @param $userId
     * @return true
     * @throws \think\Exception
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     * @Author 张旭鹏
     * @DateTime 2023-06-15
     */
    public static function cancelOrder($orderId, $userId): bool
    {
        Db::startTrans();
        $order = self::where('id', $orderId)->where('user_id', $userId)->lock(true)->find();
        if (!$order) {
            throw new Exception('订单不存在');
        }
        if ($order->status != 1) {
            DB::rollback();
            throw new Exception('订单不可取消');
        }
        $order->status = 5;
        $order->save();
        // 增加库存
        $orderGoods = $order->orderGoods;
        foreach ($orderGoods as $item) {
            HealthGoodsAttr::where('id', $item['goods_attr_id'])->setInc('stock', $item['number']);
        }
        if ($order->discount_balance > 0) {
            //取消订单退回余额
            HealthUser::where('id', $order->user_id)->setInc('balance', $order->discount_balance);
        }
        if ($order->coupon_list_id > 0) {
            //返回优惠券
            HealthCouponList::where('id', $order->coupon_list_id)->update(['status' => 0, 'order_id' => $orderId, 'use_time' => 0]);
        }
        DB::commit();
        return true;
    }

    /**
     * 确认收货
     * @param [type] $orderId
     * @param [type] $userId
     * @Author 张旭鹏
     * @DateTime 2023-06-15
     */
    public static function confirmReceipt($orderId, $userId)
    {
        $order = self::where('id', $orderId)->where('user_id', $userId)->lock(true)->find();
        if (!$order) {
            throw new Exception('订单不存在');
        }
        if ($order->status != 3) {
            throw new Exception('订单未发货');
        }
        $data['status']   = 4;
        $data['end_time'] = time();
        //把状态改成已完成
        return $order->save($data);
    }
}
